home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 2 / CU Amiga Magazine's Super CD-ROM 02 (1996)(EMAP Images)(GB)[!][issue 1996-04].iso / magazine / amiga_e / cardadd.e < prev    next >
Text File  |  1994-04-06  |  7KB  |  305 lines

  1. MODULE 'workbench/startup', 'dos/dos', 'utility/date', 'utility'
  2.  
  3. CONST MEMSTART=$600000, BLOCKSIZE=$100, FILEINFOSIZE=$20, MAGIC=$2000
  4. CONST HEADEROFF=2*BLOCKSIZE, BLKPTRSIZE=2, FILELEN=13, DEL=0, START=0
  5. CONST FREEOFF=HEADEROFF+BLOCKSIZE, HEADER=HEADEROFF+MEMSTART
  6. CONST FREEBLOCKS=FREEOFF+MEMSTART, EOFB=$FFFE, EOC=$FFFF, LEN=FILELEN-1
  7. CONST SECSPERDAY=24*60*60
  8.  
  9. ENUM NO_ERR, BAD_CARD, NO_FREE, IN_USE, W_PROTECT, SHORT_FILE, DUP_FILE,
  10.      OPEN_ERR, EXAM_ERR, BAD_DIR, TOO_BIG, OPEN_LIB
  11. ENUM FORCE, FILES
  12.  
  13. OBJECT fileinfo
  14.   file, next
  15. ENDOBJECT
  16.  
  17. RAISE EXAM_ERR IF ExamineFH()=NIL,
  18.       OPEN_ERR IF Open()=NIL,
  19.       OPEN_LIB IF OpenLibrary()=NIL
  20.  
  21. /* lastinfo is a block pointer with MAGIC, e.g., $213A (not $13A) */
  22. DEF thefiles:PTR TO fileinfo, lastfile:PTR TO fileinfo, lastinfo
  23.  
  24. PROC main() HANDLE
  25.   DEF startup:PTR TO wbstartup, wargs:PTR TO wbarg, oldlock=NIL,
  26.       templ, rdargs=NIL, args:PTR TO LONG, i, err
  27.   utilitybase:=OpenLibrary('utility.library', 37)
  28.   getinfo()
  29.   IF (startup:=wbmessage)=NIL
  30.     templ:='FORCE/S,FILE/M'
  31.     args:=[0,0]
  32.     rdargs:=ReadArgs(templ,args,NIL)
  33.     IF rdargs
  34.       IF (err:=checkwrite(args[FORCE]))<>NO_ERR THEN Raise(err)
  35.       IF args:=args[FILES]
  36.         WHILE args[]  /* Loop through arguments */
  37.           addfile(args[])
  38.           args++
  39.         ENDWHILE
  40.       ENDIF
  41.     ENDIF
  42.   ELSE
  43.     wargs:=startup.arglist
  44.     wargs++
  45.     FOR i:=1 TO startup.numargs-1  /* Loop through the arguments */
  46.       IF wargs.lock=NIL
  47.         addfile(wargs.name)
  48.       ELSE
  49.         oldlock:=CurrentDir(wargs.lock)
  50.         addfile(wargs.name)
  51.         CurrentDir(oldlock) /* Important: restore current dir */
  52.         oldlock:=NIL
  53.       ENDIF
  54.       wargs++
  55.     ENDFOR
  56.   ENDIF
  57.   Raise(NO_ERR)
  58. EXCEPT
  59.   setwrite()
  60.   IF oldlock THEN CurrentDir(oldlock)
  61.   IF rdargs THEN FreeArgs(rdargs)
  62.   IF utilitybase THEN CloseLibrary(utilitybase)
  63.   SELECT exception
  64.   CASE OPEN_LIB
  65.     WriteF('Cannot open utility library\n')
  66.   CASE BAD_CARD
  67.     WriteF('No PCMCIA card, or not from Notepad\n')
  68.   CASE IN_USE
  69.     WriteF('PCMCIA card is in use, or not from Notepad\n')
  70.   CASE W_PROTECT
  71.     WriteF('No PCMCIA card, or write protected\n')
  72.   CASE NO_FREE
  73.     WriteF('No more free blocks -- card is full\n')
  74.   ENDSELECT
  75. ENDPROC
  76.  
  77. PROC addfile(fname) HANDLE
  78.   DEF fh=NIL, file, b=START, next, len, i=0, going=TRUE,
  79.       f:PTR TO fileinfo, found=NIL, name, fib:fileinfoblock
  80.   fh:=Open(fname, OLDFILE)
  81.   name:=FilePart(fname)
  82.   ExamineFH(fh, fib)
  83.   IF fib.direntrytype>0 THEN Raise(BAD_DIR)
  84.   len:=fib.size
  85.   IF (len<=0) OR (len>$FFFF) THEN Raise(TOO_BIG)
  86.   f:=thefiles.next
  87.   WHILE f
  88.     IF deleted(f.file)
  89.       IF found=NIL THEN found:=f.file
  90.     ELSE
  91.       IF equal(name, filename(f.file)) THEN Raise(DUP_FILE)
  92.     ENDIF
  93.     f:=f.next
  94.   ENDWHILE
  95.   IF found
  96.     file:=found
  97.   ELSE
  98.     file:=FILEINFOSIZE+lastfile.file
  99.     IF Mod(file, BLOCKSIZE)=0
  100.       IF (b:=findfree(b))=EOFB THEN Raise(NO_FREE)
  101.       initblock(b)
  102.       useblock(lastinfo, b)
  103.       lastinfo:=b
  104.       useblock(b, EOC)
  105.       file:=address(b)
  106.     ENDIF
  107.   ENDIF
  108.   IF (b:=findfree(b))=EOFB THEN Raise(NO_FREE)
  109.   lastfile.next:=newfile(file)
  110.   lastfile:=lastfile.next
  111.   setfirstblock(file, b)
  112.   setname(file, name)
  113.   setdate(file, fib.datestamp)
  114.   going:=TRUE
  115.   WHILE (i<len) AND going
  116.     Read(fh, address(b), BLOCKSIZE)
  117.     i:=i+BLOCKSIZE
  118.     IF (next:=findfree(b))=EOFB
  119.       going:=FALSE
  120.     ELSE
  121.       useblock(b, next)
  122.       b:=next
  123.     ENDIF
  124.   ENDWHILE
  125.   useblock(b, EOC)
  126.   IF going=FALSE THEN Raise(SHORT_FILE)
  127.   setsize(file, len)
  128.   Raise(NO_ERR)
  129. EXCEPT
  130.   IF fh THEN Close(fh)
  131.   SELECT exception
  132.   CASE BAD_DIR
  133.     WriteF('"\s" is a directory\n', fname)
  134.   CASE TOO_BIG
  135.     WriteF('File "\s" is too large (or empty)\n', fname)
  136.   CASE OPEN_ERR
  137.     WriteF('Unable to open file "\s"\n', fname)
  138.   CASE EXAM_ERR
  139.     WriteF('Examine failed on "\s"\n', fname)
  140.   CASE DUP_FILE
  141.     WriteF('File "\s" already exists as "\s"\n', fname, filename(f.file))
  142.   CASE NO_FREE
  143.     Raise(NO_FREE)
  144.   CASE SHORT_FILE
  145.     setsize(file, i)
  146.     WriteF('File "\s" will be short\n', fname)
  147.     Raise(NO_FREE)
  148.   ENDSELECT
  149. ENDPROC
  150.  
  151. PROC getinfo()
  152.   DEF info, nofiles=FALSE, atend=FALSE, file, d
  153.   file:=HEADER
  154.   lastinfo:=firstblock(file)
  155.   thefiles:=lastfile:=newfile(file)
  156.   IF validate(file)
  157.     d:=filedate(file)
  158.     file:=file+FILEINFOSIZE
  159.     REPEAT   /* for all info blocks */
  160.       REPEAT /* for all files */
  161.         IF blank(file)
  162.           nofiles:=TRUE
  163.         ELSE
  164.           lastfile.next:=newfile(file)
  165.           lastfile:=lastfile.next
  166.           d:=filedate(file)
  167.           file:=file+FILEINFOSIZE
  168.           IF Mod(file, BLOCKSIZE)=0 THEN atend:=TRUE
  169.         ENDIF
  170.       UNTIL atend OR nofiles
  171.       IF atend
  172.         info:=follow(lastinfo)
  173.     IF (info<>EOC) AND (info<>DEL)
  174.           lastinfo:=info
  175.           file:=address(lastinfo)
  176.           atend:=FALSE
  177.         ELSE
  178.           nofiles:=TRUE
  179.         ENDIF
  180.       ENDIF
  181.     UNTIL nofiles
  182.   ELSE
  183.     Raise(BAD_CARD)
  184.   ENDIF
  185. ENDPROC
  186.  
  187. PROC checkwrite(force)
  188.   DEF err=NO_ERR, p
  189.   p:=HEADER+12
  190.   Forbid()
  191.   IF (p[]=0) OR force
  192.     p[]:=0
  193.     IF p[]<>0 THEN err:=W_PROTECT
  194.     p[]:=1
  195.     IF p[]<>1 THEN err:=W_PROTECT
  196.   ELSE
  197.     err:=IN_USE
  198.   ENDIF
  199.   Permit()
  200. ENDPROC err
  201.  
  202. PROC setwrite()
  203.   DEF p
  204.   p:=HEADER+12
  205.   Forbid()
  206.   p[]:=0
  207.   Permit()
  208. ENDPROC
  209.  
  210. PROC equal(s, t)
  211.   DEF a[LEN]:STRING, b[LEN]:STRING
  212.   StrCopy(a, s, ALL)
  213.   StrCopy(b, t, ALL)
  214.   UpperStr(a)
  215.   UpperStr(b)
  216.   RETURN StrCmp(a, b, ALL)
  217. ENDPROC
  218.  
  219. PROC follow(block) RETURN int(blockaddr(block))
  220. PROC blockaddr(block) RETURN (block-MAGIC)*BLKPTRSIZE+FREEBLOCKS
  221. PROC blockptr(addr) RETURN (addr-FREEBLOCKS)/BLKPTRSIZE+MAGIC
  222. PROC address(block) RETURN (block-MAGIC)*BLOCKSIZE+MEMSTART
  223.  
  224. PROC useblock(block, next)
  225.   putint(blockaddr(block), next)
  226. ENDPROC
  227.  
  228. PROC initblock(block)
  229.   DEF p, i
  230.   p:=address(block)
  231.   FOR i:=1 TO BLOCKSIZE DO p[]++:=0
  232. ENDPROC
  233.  
  234. PROC validate(file)
  235.   RETURN StrCmp(filename(file), 'NC', 2) AND (firstblock(file)=HEADEROFF+MAGIC)
  236. ENDPROC
  237.  
  238. PROC blank(file)
  239.   DEF n
  240.   FOR n:=0 TO FILEINFOSIZE-1 DO IF file[]++<>0 THEN RETURN FALSE
  241. ENDPROC TRUE
  242.  
  243. PROC newfile(ptr)
  244.   DEF p
  245.   CopyMem([ptr, NIL]:fileinfo, p:=New(SIZEOF fileinfo), SIZEOF fileinfo)
  246. ENDPROC p
  247.  
  248. PROC findfree(block)
  249.   DEF p, b
  250.   p:=IF block<>START THEN blockaddr(block+1) ELSE FREEBLOCKS
  251.   WHILE (b:=int(p))<>EOFB
  252.     IF b=0 THEN RETURN blockptr(p)
  253.     p:=p+BLKPTRSIZE
  254.   ENDWHILE
  255.   RETURN EOFB
  256. ENDPROC
  257.  
  258. PROC setname(file, name)
  259.   DEF i, p
  260.   p:=file
  261.   FOR i:=0 TO FILELEN DO p[]++:=0
  262.   i:=StrLen(name)
  263.   CopyMem(name, file, IF i>=FILELEN THEN FILELEN-1 ELSE i)
  264. ENDPROC
  265.  
  266. PROC setdate(file, ds:PTR TO datestamp)
  267.   DEF secs, cd:clockdata, date
  268.   secs:=Mul(ds.days,SECSPERDAY)+(ds.minute*60)+(ds.tick/50)
  269.   Amiga2Date(secs, cd)
  270.   date:=Shl(cd.year-1990, 25) OR Shl(cd.month, 21) OR Shl(cd.mday, 16) OR
  271.         Shl(cd.hour, 11) OR Shl(cd.min, 5)
  272.   putlong(file+16, date)
  273. ENDPROC
  274.  
  275. PROC setsize(file, size)
  276.   putint(file+14, size)
  277. ENDPROC
  278.  
  279. PROC setfirstblock(file, block)
  280.   putint(file+20, block)
  281. ENDPROC
  282.  
  283. PROC putint(p, v)
  284.   p[]++:=v AND $FF
  285.   p[]:=Shr(v, 8) AND $FF
  286. ENDPROC
  287.  
  288. PROC putlong(p, v)
  289.   p[]++:=v AND $FF
  290.   p[]++:=Shr(v, 8) AND $FF
  291.   p[]++:=Shr(v, 16) AND $FF
  292.   p[]:=Shr(v, 24) AND $FF
  293. ENDPROC
  294.  
  295. PROC deleted(file) RETURN file[]=0
  296. PROC filename(file) RETURN file
  297. /*
  298. PROC size(file) RETURN int(file+14)
  299. */
  300. PROC filedate(file) RETURN long(file+16)
  301. PROC firstblock(file) RETURN int(file+20)
  302.  
  303. PROC int(p) RETURN p[]++ OR Shl(p[],8)
  304. PROC long(p) RETURN p[]++ OR Shl(p[]++,8) OR Shl(p[]++,16) OR Shl(p[],24)
  305.